

const { getClient } = require('./initDbClient')
const pinyinUtil = require('../../common/utils/pinyinUtil')

const tableName = "plugin_feature_info"
const model = {
    cmdId: "string",              // 命令Id: 一个插件有多个feature，一个feature有多个命令触发
    pluginId: "string",           // 插件id
    decisionMethod: "string",     // 决策方法：根据正则，首写字母，文件类型等方法，对输入数据进行决策是否需要执行该命令
    decisionDataType: "string",   // 决策数据类型：keyword，file，folder
    decisionDataSource: "string", // 决策数据源：search(主窗口关键字搜索)，hover（鼠标选中），clipboard（粘贴板内存）
    decisionData: "string",       // 决策数据：如果是关键字直接填字符串，如果是正则直接填正则表达式，如果是
    decisionDataIndex: "string",  // 决策数据索引：对于关键词，用于生成手写字母索引

    extInfo: "json",              // 扩展字段：作为预留字段，用于用户个性化配置控制，包括是否置顶等

    cmdInfo: "json",              // 命令描述：包含code、cmdAction
    source: "string",             // 命令来源：plugin、user，用来区分是插件自带命令还是用户的，避免插件升级时把用户的插件命令删除了  
    status: "boolean",            // 状态：是否停用
    usedCnt: "int"                // 使用次数

}


function initTable(callback, force = false) {
    if (force) {
        sql = `drop table  if exists ${tableName} ; create table ${tableName} 
            ( 
                cmdId varchar(128), 
                pluginId varchar(128), 
                decisionMethod varchar(256), 
                decisionDataType varchar(256),
                decisionDataSource varchar(128),
                decisionData varchar(1024),
                decisionDataIndex varchar(2048),
                cmdInfo text,
                extInfo text,
                status varchar(8),
                source varchar(8),
                usedCnt integer  DEFAULT (0),
                gmtCreate varchar(128), 
                gmtModified varchar(128)
            )`
    } else {
        sql = `create table  if not exists ${tableName} 
            ( 
                cmdId varchar(128), 
                pluginId varchar(128), 
                decisionMethod varchar(256), 
                decisionDataType varchar(256),
                decisionDataSource varchar(128),
                decisionData varchar(1024),
                decisionDataIndex varchar(2048),
                cmdInfo text,
                extInfo text,
                status varchar(8),
                source varchar(8),
                usedCnt integer DEFAULT (0),
                gmtCreate varchar(128), 
                gmtModified varchar(128)
            )`
    }
    getClient().createTable(sql, callback)
}

function do2Models(objs) {
    const data = []
    if (objs == null) {
        return data
    }
    for (let obj of objs) {
        data.push(do2Model(obj))
    }
    return data
}

function model2Dos(objs) {
    const data = []
    if (objs == null) {
        return data
    }
    for (let obj of objs) {
        data.push(model2Do(obj))
    }
    return data
}


function do2Model(obj) {
    let model = {}

    Object.keys(obj).forEach(function (key) {
        if (key == "cmdInfo" || key == "extInfo") {
            model[key] = JSON.parse(obj[key])
        } else if (key.startsWith("gmt")) {
            model[key] = new Date(obj[key] * 1000)
        } else if (key == "status") {
            model[key] = obj[key] == "true" ? true : false
        } else {
            model[key] = obj[key]
        }
    });
    return model

}

function model2Do(obj) {
    let DO = {}
    Object.keys(obj).forEach(function (key) {
        if (key == "cmdInfo" || key == "extInfo") {
            DO[key] = JSON.stringify(obj[key])
        } else if (key.startsWith("gmt")) {
            DO[key] = parseInt(new Date().getTime() / 1000);
        } else if (key == "status") {
            DO[key] = obj[key] ? "true" : "false"
        } else {
            DO[key] = obj[key]
        }
    });

    return DO

}

exports.insert = function (model, callback) {
    const obj = model2Do(model)
    const dataItem = []
    const keys = []
    const value = []
    Object.keys(obj).forEach(function (key) {
        keys.push(key)
        if (key.startsWith("gmt")) {
            dataItem.push(obj[key])
            value.push("now()")
        } else {
            dataItem.push(obj[key])
            value.push("?")
        }
    });
    const now = parseInt(new Date().getTime() / 1000);
    keys.push("gmtCreate")
    keys.push("gmtModified")
    value.push("?")
    value.push("?")
    dataItem.push(now)
    dataItem.push(now)

    theKeys = keys.join(",")
    theValue = value.join(",")
    const insertTileSql = `insert into  ${tableName} (${theKeys}) values(${theValue})`;
    initTable(() => {
        getClient().insertData(insertTileSql, [dataItem]);
        if (callback) {
            callback()
        }
    })
}


exports.update = function (model) {
    const obj = model2Do(model)
    const cmdId = obj.cmdId
    const cmdInfo = obj.cmdInfo
    const extInfo = obj.extInfo
    const usedCnt = obj.usedCnt

    let updateSql
    const now = parseInt(new Date().getTime() / 1000);
    if (extInfo != null) {
        updateSql = `update ${tableName} set cmdInfo = '${cmdInfo}' ,extInfo ='${extInfo}',gmtModified = '${now}' where cmdId = '${cmdId}' `;
    }
    else {
        updateSql = `update ${tableName} set cmdInfo = '${cmdInfo}',gmtModified = '${now}' where cmdId = '${cmdId}' `;
    }
    initTable(() => {
        getClient().executeSql(updateSql)
    })
}


exports.addUsedCnt = function (cmdId) {
    if (cmdId != null) {
        updateSql = `update ${tableName} set usedCnt = usedCnt+1  where cmdId = '${cmdId}' `;
        initTable(() => {
            getClient().executeSql(updateSql)
        })
    }
}

exports.getPluginFeatureByCondition = function (pluginId, cmdId, source, decisionMethod, decisionDataType, decisionData, decisionDataSource, input, callback) {
    let sql = `select * from ${tableName} where 1=1`
    if (pluginId != null) {
        sql = sql + ` and pluginId= '${pluginId}'`
    }
    if (cmdId != null) {
        sql = sql + ` and cmdId= '${cmdId}'`
    }
    if (source != null) {
        sql = sql + ` and source= '${source}'`
    }
    if (decisionMethod != null) {
        sql = sql + ` and decisionMethod= '${decisionMethod}'`
    }
    if (decisionDataType != null) {
        sql = sql + ` and decisionDataType= '${decisionDataType}'`
    }
    if (decisionDataSource != null) {
        sql = sql + ` and decisionDataSource= '${decisionDataSource}'`
    }
    if (input != null) {
        sql = sql + ` and decisionDataIndex like  '%${input}%'`
    }
    if (decisionData != null) {
        sql = sql + ` and decisionData =  '${decisionData}'`
    }
    sql = sql + " order by gmtModified desc;"
    initTable(() => {
        getClient().queryData(sql, (data) => {
            callback(do2Models(data))
        })
    })

}


exports.delPluginFeatureByCondition = function (pluginId, cmdId, source, decisionMethod, decisionDataType, decisionDataSource, callback) {
    let sql = `delete  from ${tableName} where 1=1`
    if (pluginId != null) {
        sql = sql + ` and pluginId= '${pluginId}'`
    }
    if (cmdId != null) {
        sql = sql + ` and cmdId= '${cmdId}'`
    }
    if (source != null) {
        sql = sql + ` and source= '${source}'`
    }
    if (decisionMethod != null) {
        sql = sql + ` and decisionMethod= '${decisionMethod}'`
    }
    if (decisionDataType != null) {
        sql = sql + ` and decisionDataType= '${decisionDataType}'`
    }
    if (decisionDataSource != null) {
        sql = sql + ` and decisionDataSource= '${decisionDataSource}'`
    }
    initTable(() => {
        getClient().executeSql(sql, (data) => {
            callback(do2Models(data))
        })
    })

}


exports.delPluginFeatureByCmdId = function (cmdId) {
    if (cmdId == null) {
        return
    }
    let sql = `delete  from ${tableName} where cmdId='${cmdId}'`
    initTable(() => {
        getClient().executeSql(sql, (data) => { })
    })
}


exports.switchStatusPluginFeatureByCondition = function (pluginId, type, cmdId, status) {
    let statusValue = status ? "true" : "false"
    let sql = `update   ${tableName} set status='${statusValue}' where 1=1`
    if (cmdId != null) {
        sql = sql + ` and  cmdId='${cmdId}'`
    }
    if (pluginId != null) {
        sql = sql + ` and  cmdId='${pluginId}'`
    }
    if (type != null) {
        sql = sql + ` and  type='${type}'`
    }

    initTable(() => {
        getClient().executeSql(sql, () => { })
    })

}


exports.composeModel = function (pluginId, cmdId, decisionMethod, decisionDataType, decisionDataSource, decisionData, source, cmdInfo, extInfo) {
    return {
        pluginId: pluginId,
        cmdId: cmdId,
        decisionMethod: decisionMethod,
        decisionDataType: decisionDataType,
        decisionDataSource: decisionDataSource,
        decisionData: decisionData,
        decisionDataIndex: genIndex(decisionData, decisionMethod),
        source: source,
        cmdInfo: cmdInfo,
        status: true,
        extInfo: extInfo
    }
}


function genIndex(decisionData, decisionMethod) {
    if (decisionMethod == "initials") {
        return pinyinUtil.parseKeyword(decisionData)
    } else {
        return null
    }
}